﻿using System;
using System.Collections.Generic;
using System.Text;
using RoughJs.Ast;

namespace RoughJs.E4X
{
    public class XMLCtor:IdFunctionObject
    {
        private static  Object XMLCTOR_TAG = "XMLCtor";

    private XmlProcessor options;
//    private XMLLibImpl lib;

  public  XMLCtor(XML xml, Object tag, int id, int arity):base(xml, tag, id, arity)
    {
       
//        this.lib = xml.lib;
        this.options = xml.getProcessor();
        activatePrototypeMap(MAX_FUNCTION_ID);
    }

    private void writeSetting(Scriptable target)
    {
        for (int i = 1; i <= MAX_INSTANCE_ID; ++i) {
            int id = base.getMaxInstanceId() + i;
            String name = getInstanceIdName(id);
            Object value = getInstanceIdValue(id);
            ScriptableObject.putProperty(target, name, value);
        }
    }

    private void readSettings(Scriptable source)
    {
        for (int i = 1; i <= MAX_INSTANCE_ID; ++i) {
            int id = base.getMaxInstanceId() + i;
            String name = getInstanceIdName(id);
            Object value = ScriptableObject.getProperty(source, name);
            if (value == ScriptableObject.NOT_FOUND) {
                continue;
            }
            switch (i) {
              case Id_ignoreComments:
              case Id_ignoreProcessingInstructions:
              case Id_ignoreWhitespace:
              case Id_prettyPrinting:
                if (!(value is  Boolean)) {
                    continue;
                }
                break;
              case Id_prettyIndent:
                if (!(ScriptRuntime.isNumber(value))) {
                    continue;
                }
                break;
              default:
                throw new Exception();
            }
            setInstanceIdValue(id, value);
        }
    }

// #string_id_map#

    private const int
        Id_ignoreComments               = 1,
        Id_ignoreProcessingInstructions = 2,
        Id_ignoreWhitespace             = 3,
        Id_prettyIndent                 = 4,
        Id_prettyPrinting               = 5,

        MAX_INSTANCE_ID                 = 5;


    public override int getMaxInstanceId()
    {
        return base.getMaxInstanceId() + MAX_INSTANCE_ID;
    }

  
    public override  int findInstanceIdInfo(String s) {
        int id;

        id = 0; String X = null; int c;
             switch (s.Length) {
            case 12: X="prettyIndent";id=Id_prettyIndent; goto L;
            case 14: c=s.ToCharArray()[0];
                if (c=='i') { X="ignoreComments";id=Id_ignoreComments; }
                else if (c=='p') { X="prettyPrinting";id=Id_prettyPrinting; }
                goto L;
            case 16: X="ignoreWhitespace";id=Id_ignoreWhitespace; goto L;
            case 28: X="ignoreProcessingInstructions";id=Id_ignoreProcessingInstructions; goto L;
            }L:;
            if (X!=null && X!=s && !(X==s)) id = 0;
            goto L0;
         L0: ;

        if (id == 0) return base.findInstanceIdInfo(s);

        int attr;
        switch (id) {
          case Id_ignoreComments:
          case Id_ignoreProcessingInstructions:
          case Id_ignoreWhitespace:
          case Id_prettyIndent:
          case Id_prettyPrinting:
            attr = PERMANENT | DONTENUM;
            break;
          default: throw new Exception();
        }
        return instanceIdInfo(attr, base.getMaxInstanceId() + id);
    }

// #/string_id_map#


    public override  String getInstanceIdName(int id)
    {
        switch (id - base.getMaxInstanceId()) {
          case Id_ignoreComments:               return "ignoreComments";
          case Id_ignoreProcessingInstructions: return "ignoreProcessingInstructions";
          case Id_ignoreWhitespace:             return "ignoreWhitespace";
          case Id_prettyIndent:                 return "prettyIndent";
          case Id_prettyPrinting:               return "prettyPrinting";
        }
        return base.getInstanceIdName(id);
    }


    public override  Object getInstanceIdValue(int id)
    {
        switch (id - base.getMaxInstanceId()) {
          case Id_ignoreComments:
            return ScriptRuntime.wrapBoolean(options.isIgnoreComments());
          case Id_ignoreProcessingInstructions:
            return ScriptRuntime.wrapBoolean(options.isIgnoreProcessingInstructions());
          case Id_ignoreWhitespace:
            return ScriptRuntime.wrapBoolean(options.isIgnoreWhitespace());
          case Id_prettyIndent:
            return ScriptRuntime.wrapInt(options.getPrettyIndent());
          case Id_prettyPrinting:
            return ScriptRuntime.wrapBoolean(options.isPrettyPrinting());
        }
        return base.getInstanceIdValue(id);
    }

   
    public override  void setInstanceIdValue(int id, Object value) {
        switch (id - base.getMaxInstanceId()) {
            case Id_ignoreComments:
                options.setIgnoreComments(ScriptRuntime.toBoolean(value));
                return;
            case Id_ignoreProcessingInstructions:
                options.setIgnoreProcessingInstructions(ScriptRuntime.toBoolean(value));
                return;
            case Id_ignoreWhitespace:
                options.setIgnoreWhitespace(ScriptRuntime.toBoolean(value));
                return;
            case Id_prettyIndent:
                options.setPrettyIndent(ScriptRuntime.toInt32(value));
                return;
            case Id_prettyPrinting:
                options.setPrettyPrinting(ScriptRuntime.toBoolean(value));
                return;
        }
        base.setInstanceIdValue(id, value);
    }

// #string_id_map#
    private const int
        Id_defaultSettings              = 1,
        Id_settings                     = 2,
        Id_setSettings                  = 3,
        MAX_FUNCTION_ID                 = 3;

    
    public override  int findPrototypeId(String s)
    {
        int id;

         id = 0; String X = null;
            int s_length = s.Length;
            if (s_length==8) { X="settings";id=Id_settings; }
            else if (s_length==11) { X="setSettings";id=Id_setSettings; }
            else if (s_length==15) { X="defaultSettings";id=Id_defaultSettings; }
            if (X!=null && X!=s && !(X==s)) id = 0;
            goto L0;
        L0: ;

        return id;
    }


    public override  void initPrototypeId(int id)
    {
        String s;
        int arity;
        switch (id) {
          case Id_defaultSettings:  arity=0; s="defaultSettings";  break;
          case Id_settings:         arity=0; s="settings";         break;
          case Id_setSettings:      arity=1; s="setSettings";      break;
          default: throw new ArgumentException(id.ToString());
        }
        initPrototypeMethod(XMLCTOR_TAG, id, s, arity);
    }

 
    public override  Object execIdCall(IdFunctionObject f, Context cx, Scriptable scope,
                             Scriptable thisObj, Object[] args)
    {
        if (!f.hasTag(XMLCTOR_TAG)) {
            return base.execIdCall(f, cx, scope, thisObj, args);
        }
        int id = f.methodId();
        switch (id) {
          case Id_defaultSettings: {
            options.setDefault();
            Scriptable obj = cx.newObject(scope);
            writeSetting(obj);
            return obj;
          }
          case Id_settings: {
            Scriptable obj = cx.newObject(scope);
            writeSetting(obj);
            return obj;
          }
          case Id_setSettings: {
            if (args.Length == 0
                || args[0] == null
                || args[0] == Undefined.instance)
            {
                options.setDefault();
            } else if (args[0] is  Scriptable) {
                readSettings((Scriptable)args[0]);
            }
            return Undefined.instance;
          }
        }
        throw new ArgumentException(id.ToString());
    }

    /**
        hasInstance for XML objects works differently than other objects; see ECMA357 13.4.3.10.
     */
    public override bool hasInstance(Scriptable instance)
    {
        return (instance is  XML || instance is  XMLList);
    }
    }// end for class
}
